package com.pai4j.pgc.service.community;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.pai4j.common.enums.community.PromptTemplateEnum;
import com.pai4j.common.service.FreeMarkEngineService;
import com.pai4j.common.util.JsonUtil;
import com.pai4j.common.util.RedisUtil;
import com.pai4j.common.util.community.AiResponseUtil;
import com.pai4j.common.util.community.MindMapToMarkdownConverter;
import com.pai4j.domain.community.dto.ai.VideoMindMapSummaryDTO;
import com.pai4j.domain.community.dto.ai.VideoSummaryDTO;
import com.pai4j.domain.community.dto.audio.AudioTextJsonNode;
import com.pai4j.domain.community.vo.request.aig.ChatRequestVO;
import com.pai4j.domain.community.vo.response.cc.CCVideoSummaryRespDTO;
import com.pai4j.domain.vo.llm.ChatCompletionMessage;
import com.pai4j.domain.vo.llm.ChatCompletionResponse;
import com.pai4j.domain.vo.llm.ChatMessageRole;
import com.pai4j.pgc.dao.community.ICCVideoDAO;
import com.pai4j.pgc.dao.community.ICCVideoSummaryDAO;
import com.pai4j.pgc.entity.community.CCVideoEntity;
import com.pai4j.pgc.entity.community.CCVideoSummaryEntity;
import com.pai4j.pgc.service.aig.DeepSeekAIService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CCVideoSummaryService {

    @Autowired
    private ICCVideoSummaryDAO videoSummaryDAO;
    @Autowired
    private ICCVideoDAO videoDAO;

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private FreeMarkEngineService freeMarkEngineService;
    @Autowired
    private DeepSeekAIService deepSeekAIService;

    private static final String audio = "https://coderutil.oss-cn-beijing.aliyuncs.com/chat4j_video_audio/55.mp3";
    private static final String AK = "LTAI5tGEjtk3WZYv93sY3osn";
    private static final String SK = "QjRuNIk5viLnZ4ZTCCfPdGg2SGIUSo";

    public boolean hasSummary(Long videoId) {
        String cacheKey = CTCRedisKeyEnum.CTC_VIDEO_HAS_SUMMARY_ID_SET.getKey();
        if (!redisUtil.exists(cacheKey)) {
            initSummaryVideoIds();
        }
        return redisUtil.sIsMember(cacheKey, String.valueOf(videoId));
    }

    private void delSummaryVideoCache() {
        String cacheKey = CTCRedisKeyEnum.CTC_VIDEO_HAS_SUMMARY_ID_SET.getKey();
        redisUtil.remove(cacheKey);
    }

    public Map<Long, Boolean> hasSummary(List<Long> videoIds) {
        Set<Long> hashSummaryVideoIds = getAllSummaryVideoIds();
        Map<Long, Boolean> map = new HashMap<>();
        for (Long videoId : videoIds) {
            map.put(videoId, hashSummaryVideoIds.contains(videoId));
        }
        return map;
    }

    public Set<Long> getAllSummaryVideoIds() {
        String cacheKey = CTCRedisKeyEnum.CTC_VIDEO_HAS_SUMMARY_ID_SET.getKey();
        if (!redisUtil.exists(cacheKey)) {
            initSummaryVideoIds();
        }
        Set<String> videoIdArr = redisUtil.smembers(cacheKey);
        if (CollectionUtils.isEmpty(videoIdArr)) {
            return new HashSet<>();
        }
        return videoIdArr.stream().map(Long::parseLong).collect(Collectors.toSet());
    }

    private Set<Long> initSummaryVideoIds() {
        String cacheKey = CTCRedisKeyEnum.CTC_VIDEO_HAS_SUMMARY_ID_SET.getKey();
        List<Long> videoIds = videoSummaryDAO.findAllCompletedIds();
        if (CollectionUtils.isNotEmpty(videoIds)) {
            Set<String> videoIdArr = videoIds.stream().map(String::valueOf).collect(Collectors.toSet());
            redisUtil.sadd(cacheKey, videoIdArr);
            redisUtil.expire(cacheKey, CTCRedisKeyEnum.CTC_VIDEO_HAS_SUMMARY_ID_SET.getExpireTime());
        }
        return videoIds == null ? new HashSet<>() : new HashSet<>(videoIds);
    }


    public void doSummary() {
        List<CCVideoEntity> videoEntities = videoDAO.findAllByPathIdAndIdGreaterThanEqualOrderByIdAsc(28L, 176L);
        for (CCVideoEntity videoEntity : videoEntities) {
            try {
                // 获取任务id
                String res = summarization("https://coderutil.oss-cn-beijing.aliyuncs.com/chat4j_video_audio/"+videoEntity.getId()+".mp3");
                JsonNode jsonNode = JsonUtil.fromJson(res, JsonNode.class);
                String taskId = jsonNode.get("Data").get("TaskId").asText();
                String content = "";
                String markdown = "";
                String summarization = "";
                String summarizationNodeJson = "";
                String summarizationJson = "";
                boolean whileStatus = true;
                while (whileStatus) {
                    String taskInfo = getTaskInfo(taskId);
                    JsonNode taskInfoNode = JsonUtil.fromJson(taskInfo, JsonNode.class);
                    String taskStatus = taskInfoNode.get("Data").get("TaskStatus").asText();
                    if (taskStatus.equals("COMPLETED")) {
                        whileStatus = false;
                        if (!redisUtil.installDistributedLock("VIDEO_SUMMARY_LOCK_2_" + videoEntity.getId(), "1", 10 * 60)) {
                            break;
                        }
                        JsonNode taskResultNode = taskInfoNode.get("Data").get("Result");
                        String transcription = taskResultNode.get("Transcription").asText();
                        summarization = taskResultNode.get("Summarization").asText();
                        summarizationJson = getJsonFromUrl(summarization);
                        JsonNode summarizationNode = JsonUtil.fromJson(summarizationJson, JsonNode.class);
                        summarizationNodeJson = JsonUtil.toJsonString(summarizationNode.get("Summarization"));
                        List<VideoMindMapSummaryDTO> nodes = JsonUtil.fromJson(
                                JsonUtil.toJsonString(summarizationNode.get("Summarization").get("MindMapSummary")),
                                new TypeReference<List<VideoMindMapSummaryDTO>>() {});
                        MindMapToMarkdownConverter converter = new MindMapToMarkdownConverter();
                        markdown = converter.convertMD(nodes);
                        content = getContent(transcription);
                        String kimiSummary = doSummaryByLLM(content);
                        if (StringUtils.isNotBlank(markdown) &&
                                StringUtils.isNotBlank(summarizationNodeJson) &&
                                StringUtils.isNotBlank(content)) {
                            Date now = new Date();
                            CCVideoSummaryEntity videoSummaryEntity = new CCVideoSummaryEntity();
                            videoSummaryEntity.setVideoId(videoEntity.getId());
                            videoSummaryEntity.setTaskId(taskId);
                            videoSummaryEntity.setMindMapSummary(markdown);
                            videoSummaryEntity.setSummarization(summarizationNodeJson);
                            videoSummaryEntity.setContent(content);
                            videoSummaryEntity.setSummary(kimiSummary);
                            videoSummaryEntity.setCreateDate(now);
                            videoSummaryEntity.setUpdateDate(now);
                            videoSummaryEntity.setStatus("COMPLETED");
                            videoSummaryDAO.save(videoSummaryEntity);
                            delSummaryCache(videoEntity.getId());
                            delSummaryVideoCache();
                            log.info("视频完成智能总结 ===> videoId:{}, title:{}, taskId:{}",
                                    videoEntity.getId(), videoEntity.getTitle(), taskId);
                        }
                    } else {
                        Thread.sleep(10000);
                    }
                }
            } catch (Exception e) {
                log.error("音频处理失败 ===> videoId:{}", videoEntity.getId(), e);
            }
        }
    }

    private String doSummaryByLLM(String content) {
        Map<String, Object> vars = new HashMap<>();
        vars.put("content", content);
        try {
            String prompt = freeMarkEngineService.getContentByTemplate(PromptTemplateEnum.CC_VIDEO_SUMMARY.getName(), vars);
            ChatRequestVO chatRequest = new ChatRequestVO();
            chatRequest.setText(prompt);
            final List<ChatCompletionMessage> messageList = Arrays.asList(
                    new ChatCompletionMessage(ChatMessageRole.USER.value(), prompt));
            ChatCompletionResponse chatCompletionResponse = deepSeekAIService.chat(messageList);
            return AiResponseUtil.getHtmlString(chatCompletionResponse.getChoices().get(0).getMessage().getContent());
        } catch (Exception e) {
            log.error("===>execAiBotTask error.", e);
        }
        return null;
    }

    public void generateAudio (Long id){
        List<CCVideoEntity> videoEntities = videoDAO.findAllByPathIdAndIdGreaterThanEqualOrderByIdAsc(28L, id);
        for (CCVideoEntity videoEntity : videoEntities) {
            doGenerateAudio(videoEntity.getId(), videoEntity.getVideo());
        }
    }

    private void doGenerateAudio(Long id, String video) {
        List<String> command = new ArrayList<>();
        command.add("ffmpeg");
        command.add("-i");
        command.add(video);
        command.add("-vn");
        command.add("-c:a");
        command.add("libmp3lame");
        command.add("-q:a");
        command.add("2");
        command.add("/Users/wangqi49/Desktop/chat4j_video_audio/" + id + ".mp3");

        try {
            ProcessBuilder builder = new ProcessBuilder(command);
            builder.redirectErrorStream(true); // 合并错误流和输出流
            Process process = builder.start();

            // 读取输出信息
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            int exitCode = process.waitFor();
            System.out.println("Exited with code: " + exitCode);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询视频总结内容
     *
     * @param videoId
     * @return
     */
    public CCVideoSummaryRespDTO summary(Long videoId) {

        String cacheKey = CTCRedisKeyEnum.CTC_VIDEO_SUMMARY_DETAIL_CACHE.getKey(String.valueOf(videoId));
        String cache = redisUtil.get(cacheKey);
        if (StringUtils.isNotBlank(cache)) {
            return JsonUtil.fromJson(cache, CCVideoSummaryRespDTO.class);
        }
        CCVideoSummaryRespDTO summary = summaryByDB(videoId);
        if (summary != null) {
            redisUtil.set(cacheKey, JsonUtil.toJsonString(summary), CTCRedisKeyEnum.CTC_VIDEO_SUMMARY_DETAIL_CACHE.getExpireTime());
        }
        return summary;
    }

    private void delSummaryCache(Long videoId) {
        String cacheKey = CTCRedisKeyEnum.CTC_VIDEO_SUMMARY_DETAIL_CACHE.getKey(String.valueOf(videoId));
        redisUtil.remove(cacheKey);
    }

    public CCVideoSummaryRespDTO summaryByDB(Long videoId) {

        CCVideoSummaryEntity entity = videoSummaryDAO.findByVideoIdAndStatus(videoId, "COMPLETED");
        if (entity == null) {
            return null;
        }
        String summarization = entity.getSummarization();
        CCVideoSummaryRespDTO summary = new CCVideoSummaryRespDTO();
        summary.setId(entity.getId());
        summary.setVideoId(entity.getVideoId());
        summary.setSummarization(JsonUtil.fromJson(summarization, VideoSummaryDTO.class));
        summary.setSummary(entity.getSummary());
        summary.setMindMapMarkdown(entity.getMindMapSummary());
        summary.setStatus(entity.getStatus());
        return summary;
    }

    public static void testFiletrans() throws ClientException {
        CommonRequest request = createCommonRequest("tingwu.cn-beijing.aliyuncs.com", "2023-09-30", ProtocolType.HTTPS, MethodType.PUT, "/openapi/tingwu/v2/tasks");
        request.putQueryParameter("type", "offline");

        JSONObject root = new JSONObject();
        root.put("AppKey", "7kyhbUvPlEdJtG");

        JSONObject input = new JSONObject();
        input.fluentPut("FileUrl", audio)
                .fluentPut("SourceLanguage", "cn")
                .fluentPut("TaskKey", "task" + System.currentTimeMillis());
        root.put("Input", input);

        JSONObject parameters = new JSONObject();
        JSONObject transcription = new JSONObject();
        transcription.put("DiarizationEnabled", true);
        JSONObject speakerCount = new JSONObject();
        speakerCount.put("SpeakerCount", 2);
        transcription.put("Diarization", speakerCount);
        parameters.put("Transcription", transcription);
        root.put("Parameters", parameters);
        System.out.println(root.toJSONString());
        request.setHttpContent(root.toJSONString().getBytes(), "utf-8", FormatType.JSON);

        DefaultProfile profile = DefaultProfile.getProfile("cn-beijing", AK, SK);
        IAcsClient client = new DefaultAcsClient(profile);
        CommonResponse response = client.getCommonResponse(request);
        System.out.println(response.getData());
    }

    public static CommonRequest createCommonRequest(String domain, String version, ProtocolType protocolType, MethodType method, String uri) {
        // 创建API请求并设置参数
        CommonRequest request = new CommonRequest();
        request.setSysDomain(domain);
        request.setSysVersion(version);
        request.setSysProtocol(protocolType);
        request.setSysMethod(method);
        request.setSysUriPattern(uri);
        request.setHttpContentType(FormatType.JSON);
        return request;
    }

    public static String getTaskInfo(String taskId) throws ClientException {
        String queryUrl = String.format("/openapi/tingwu/v2/tasks" + "/%s", taskId);
        CommonRequest request = createCommonRequest("tingwu.cn-beijing.aliyuncs.com", "2023-09-30", ProtocolType.HTTPS, MethodType.GET, queryUrl);
        // TODO 请通过环境变量设置您的AccessKeyId、AccessKeySecret
        DefaultProfile profile = DefaultProfile.getProfile("cn-beijing", AK, SK);
        IAcsClient client = new DefaultAcsClient(profile);
        CommonResponse response = client.getCommonResponse(request);
        System.out.println(response.getData());
        return response.getData();
    }

    public static String summarization(String audioUrl) throws ClientException {
        CommonRequest request = createCommonRequest("tingwu.cn-beijing.aliyuncs.com", "2023-09-30", ProtocolType.HTTPS, MethodType.PUT, "/openapi/tingwu/v2/tasks");
        request.putQueryParameter("type", "offline");

        JSONObject root = new JSONObject();
        root.put("AppKey", "7kyhbUvPlEdJtG");

        JSONObject input = new JSONObject();
        input.fluentPut("FileUrl", audioUrl)
                .fluentPut("SourceLanguage", "cn")
                .fluentPut("TaskKey", "task" + System.currentTimeMillis());
        root.put("Input", input);

        JSONObject parameters = new JSONObject();
        parameters.put("SummarizationEnabled", true);
        JSONObject summarization = new JSONObject();
        // 全文摘要、发言人总结摘要、问答摘要(问答回顾)
        JSONArray types = new JSONArray()
                .fluentAdd("Paragraph")
                .fluentAdd("Conversational")
                .fluentAdd("QuestionsAnswering")
                .fluentAdd("MindMap");
        summarization.put("Types", types);
        parameters.put("Summarization", summarization);
        root.put("Parameters", parameters);
        System.out.println(root.toJSONString());
        request.setHttpContent(root.toJSONString().getBytes(), "utf-8", FormatType.JSON);

        // TODO 请通过环境变量设置您的AccessKeyId、AccessKeySecret
        DefaultProfile profile = DefaultProfile.getProfile("cn-beijing", AK, SK);
        IAcsClient client = new DefaultAcsClient(profile);
        CommonResponse response = client.getCommonResponse(request);
        return response.getData();
    }

    public static String getJsonFromUrl(String urlString) throws Exception {
        URL url = new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        int responseCode = connection.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK) {
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(connection.getInputStream()));
            String inputLine;
            StringBuilder response = new StringBuilder();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();

            return response.toString();
        } else {
            throw new RuntimeException("HTTP GET请求失败，错误码: " + responseCode);
        }
    }

    public static String getContent(String url) {
        try {
            String audioTextJson = getJsonFromUrl(url);
            AudioTextJsonNode audioTextJsonNode = JsonUtil.fromJson(audioTextJson, AudioTextJsonNode.class);
            StringBuilder content = new StringBuilder();
            audioTextJsonNode.getTranscription().getParagraphs().forEach(p ->
            {
                Long startTime = p.getWords().get(0).getStart();
                Long endTime = p.getWords().get(p.getWords().size() - 1).getEnd();
                content.append(String.format("\n[%s, %s]", startTime, endTime));
                p.getWords().forEach(w -> {
                    content.append(w.getText());
                });
            });
            return content.toString();
        } catch (Exception e) {
            return null;
        }
    }

    public static void main(String[] args) {
        try {
//            testFiletrans();
//            getTaskInfo("65ee9f18b3b34de0b09d963be26d1ddf");
//
            String res = summarization("https://coderutil.oss-cn-beijing.aliyuncs.com/chat4j_video_audio/55.mp3");
            JsonNode jsonNode = JsonUtil.fromJson(res, JsonNode.class);
            String taskId = jsonNode.get("Data").get("TaskId").asText();
            String content = "";
            String markdown = "";
            boolean whileStatus = true;
            while (whileStatus) {
                String taskInfo = getTaskInfo(taskId);
                JsonNode taskInfoNode = JsonUtil.fromJson(taskInfo, JsonNode.class);
                String taskStatus = taskInfoNode.get("Data").get("TaskStatus").asText();
                if (taskStatus.equals("COMPLETED")) {
                    JsonNode taskResultNode = taskInfoNode.get("Data").get("Result");
                    String transcription = taskResultNode.get("Transcription").asText();
                    String summarization = taskResultNode.get("Summarization").asText();
                    JsonNode summarizationNode = JsonUtil.fromJson(getJsonFromUrl(summarization), JsonNode.class);
                    String mindMapSummary = summarizationNode.get("Summarization").get("MindMapSummary").asText();
                    content = getContent(transcription);
                    List<VideoMindMapSummaryDTO> nodes = JsonUtil.fromJson(
                            JsonUtil.toJsonString(summarizationNode.get("Summarization").get("MindMapSummary")),
                            new TypeReference<List<VideoMindMapSummaryDTO>>() {});
                    MindMapToMarkdownConverter converter = new MindMapToMarkdownConverter();
                    markdown = converter.convertMD(nodes);
                    whileStatus = false;
                } else {
                    Thread.sleep(5000);
                }
            }
            System.out.println("content ==> " + content);
            System.out.println("markdown ==> " + markdown);

            //            getTaskInfo("6032edb9ea5f4a98a368e0366032f056");
//            getContent("https://prod-tingwu-paas-common-beijing.oss-cn-beijing.aliyuncs.com/tingwu/output/1785603244716915/6032edb9ea5f4a98a368e0366032f056/6032edb9ea5f4a98a368e0366032f056_Transcription_20250908224300.json?Expires=1759934602&OSSAccessKeyId=LTAI5tMzZ1D4o1drkJN1TfCr&Signature=iKVf%2BA3BN6BLZNglBv%2Fqm3%2F6ppA%3D");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
